package com.hh.base.common;

import com.hh.base.util.StringUtil;

import java.util.List;

/**
 * Created by liuhanhui on 2017/11/1.
 */
public class Template {


    private static final String PACKAGE = "{package}";

    private static final String ERROR_CODES = "{error_codes}";

    private static final String MODEL_MAPPINGS = "{modelmappings}";

    private static final String MODEL_NAME = "{modelname}";

    private static final String TABLE_NAME = "{tabelname}";

    private static final String TABLE_KEY = "{keys}";

    private static final String TABLE_FIELD = "{fileds}";

    private static final String TABLE_GSTTER = "{gstter}";

    private static final String SERIVCE_NAME = "{servicename}";

    private static String TEMPLATE_FIELD = "private {type} {name1};";

    private static String TEMPLATE_KEYS = "public static final String KEY_{name3} = \"{name0}\";";

    private static String TEMPLATE_METHOD_GET = "public {type} get{name2}() {\n\t\treturn this.get(\"{name0}\");\n\t}";

    private static String TEMPLATE_METHOD_SET = "public void set{name2}({type} {name1}) {\n\t\tthis.set(\"{name0}\", {name1});\n\t}";

    private static String TEMPLATE_MAPPING = "activeRecordPlugin.addMapping({modelname}.TABLE_NAME, {modelname}.class);";

    private String content;

    private Template() {

    }

    public Template(String content) {
        this.content = content;
    }

    public void build(String packageName, String modelName, String tableName, String serviceName, TableBean tableBean, List<TableBean> tableBeans) {
        if (this.content.contains(PACKAGE)) {
            this.buildPackage(packageName);
        }

        if (this.content.contains(MODEL_NAME)) {
            this.buildModelName(modelName);
        }

        if (this.content.contains(TABLE_NAME)) {
            this.buildTableName(tableName);
        }

        if (this.content.contains(TABLE_KEY)) {
            this.buildTableKeys(tableBean);
        }

        if (this.content.contains(TABLE_FIELD)) {
            this.buildTableFields(tableBean);
        }
        if (this.content.contains(TABLE_GSTTER)) {
            this.buildGstter(tableBean);
        }

        if (this.content.contains(SERIVCE_NAME)) {
            this.buildService(tableBean);
        }

        if (this.content.contains(MODEL_MAPPINGS)) {
            this.buildModelMapping(tableBeans);
        }
    }

    private Template buildPackage(String packageName) {
        this.content = this.content.replace(PACKAGE, packageName);
        return this;
    }

    private Template buildModelName(String modelName) {
        this.content = this.content.replace(MODEL_NAME, modelName);
        return this;
    }

    private Template buildTableName(String tableName) {
        this.content = this.content.replace(TABLE_NAME, tableName);
        return this;
    }

    private Template buildTableKeys(TableBean tableBean) {
        StringBuilder keySB = new StringBuilder("");
        List<FiledBean> filedBeanList = tableBean.getFiledBeanList();
        for (FiledBean filedBean :
                filedBeanList) {
            String name0 = filedBean.getName();
            String name3 = name0.toUpperCase();
            keySB.append("\t").append(TEMPLATE_KEYS.replace("{name3}", name3).replace("{name0}", name0)).append("\n\n");
        }

        this.content = this.content.replace(TABLE_KEY, keySB.toString());
        return this;
    }

    private Template buildTableFields(TableBean tableBean) {
        List<FiledBean> filedBeanList = tableBean.getFiledBeanList();
        StringBuilder filedSB = new StringBuilder("");
        for (FiledBean filedBean :
                filedBeanList) {
            String type = parseFieldType(filedBean.getType());
            String name0 = filedBean.getName();
            String name1 = StringUtil.formatArgsName(name0);
            filedSB.append("\t//" + filedBean.getComment()).append("\n");
            String tempField = TEMPLATE_FIELD.replace("{type}", type).replace("{name1}", name1);
            filedSB.append("\t").append(tempField).append("\n\n");

        }
        this.content = this.content.replace(TABLE_FIELD, filedSB.toString());
        return this;
    }

    private Template buildGstter(TableBean tableBean) {
        List<FiledBean> filedBeanList = tableBean.getFiledBeanList();
        StringBuilder methodSB = new StringBuilder("");
        for (FiledBean filedBean :
                filedBeanList) {
            String type = parseFieldType(filedBean.getType());
            String name0 = filedBean.getName();
            String name1 = StringUtil.formatArgsName(name0);
            String name2 = StringUtil.toUpperCase4Index(name1);
            String tempMethodGet = TEMPLATE_METHOD_GET.replace("{type}", type).replace("{name2}", name2).replace("{name0}", name0);
            String tempMethodSet = TEMPLATE_METHOD_SET.replace("{type}", type).replace("{name2}", name2).replace("{name1}", name1).replace("{name0}", name0);
            methodSB.append("\t").append(tempMethodGet + "\n\n");
            methodSB.append("\t").append(tempMethodSet + "\n\n");

        }
        this.content = this.content.replace(TABLE_GSTTER, methodSB.toString());
        return this;
    }

    private Template buildService(TableBean tableBean) {
        String name1 = StringUtil.formatArgsName(tableBean.getName());
        String name2 = StringUtil.toUpperCase4Index(name1);
        String serviceName = name2 + "Service";
        this.content = this.content.replace("{name1}", name1);
        this.content = this.content.replace(SERIVCE_NAME, serviceName);
        return this;
    }


    private Template buildModelMapping(List<TableBean> tableBeans) {
        StringBuilder sb = new StringBuilder();
        for (TableBean tableBean :
                tableBeans) {
            String modelName = StringUtil.toUpperCase4Index(StringUtil.formatArgsName(tableBean.getName())) + "Model";
            String tempMapping = TEMPLATE_MAPPING.replace("{modelname}", modelName);
            sb.append("\t\t" + tempMapping + "\n");
        }

        this.content = this.content.replace(MODEL_MAPPINGS, sb.toString());
        return this;
    }

//    private Template buildErrorCode() {
//
//    }

    private String parseFieldType(String type) {
        if ("int".equals(type)) {
            return "int";
        }

        if ("varchar".equals(type)) {
            return "String";
        }

        if ("datetime".equals(type)) {
            return "Date";
        }
        return type;
    }

    public String getContent() {
        return content;
    }
}
